home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / libdmalloc / README < prev    next >
Encoding:
Text File  |  1994-08-02  |  18.2 KB  |  359 lines

  1.  
  2.                 ~4Dgifts/toolbox/public/libdmalloc README
  3.  
  4.  
  5.     Libdmalloc is a debugging malloc library I wrote with ideas I stole from 
  6.     Conor P. Cahill's dbmalloc, Brandyn Webb's malloc-debug, Kipp Hickman's
  7.     "leaky", Purify, and sgi's old dbx source.  It is not a finished product. 
  8.     Currently the only environment in which it works is IRIX5 and maybe IRIX4
  9.     (the only problem with IRIX4 should be benign complaints regarding getwd).
  10.     I believe it is MP-safe.  
  11.  
  12.     It's very useful for finding memory corruption quickly in many different 
  13.     programs, since it has little overhead and does not require programs to 
  14.     be compiled in any special way.  It uses the ability to plug in different
  15.     a malloc library using DSOs.
  16.  
  17.     Please send all questions and comments to me, Don Hatch (hatch@sgi.com).
  18.  
  19. ===============================================================================
  20.  
  21. WHAT LIBDMALLOC DOES
  22.  
  23.     libdmalloc.a contains the following standard functions:
  24.         malloc
  25.         free
  26.         realloc
  27.         calloc
  28.         cfree
  29.     These are actually wrappers for the functions from libmalloc.a,
  30.     which are also included in libdmalloc, but with disguised names
  31.     mAlLoC, fReE, etc.
  32.     The wrapper functions maintain malloc statistics, and do the following 
  33.     other good stuff:
  34.        -- Initialize newly malloced memory to 1's, to break
  35.           programs that depend on it being 0's
  36.        -- Fill freed memory with 2's, to break programs that
  37.           look at freed memory.
  38.        -- free() and realloc() do sanity checks to make sure
  39.       the area immediately surrounding the memory has not
  40.       been modified (8 bytes or so on either side).
  41.       If corruption is detected, it attempts to print a current
  42.       stacktrace and also a stacktrace of the original malloc if possible.
  43.        -- during exit(), all malloced memory is checked for corruption.
  44.  
  45. ===============================================================================
  46.  
  47. LINKING A PROGRAM WITH LIBDMALLOC
  48.  
  49.     There are two ways to link libdmalloc into your program.
  50.     The first is simply to tell rld to do it at runtime:
  51.         setenv _RLD_LIST /usr/tmp/libdmalloc.so:DEFAULT
  52.     Then any non-setuid dynamic executable you run (use the 'file' program
  53.     to determine whether an executable is dynamic or not) will use libdmalloc.
  54.     [[ Hint: if you will want to run dbx on a stripped executable, dbx will
  55.     work better (i.e. be able to make interactive calls) if your
  56.     _RLD_LIST also contains crt1.so.  You can make one of these as follows:
  57.         ld -shared /usr/lib/crt1.o -o /usr/tmp/crt1.so
  58.         setenv _RLD_LIST /usr/tmp/libdmalloc.so:/usr/tmp/crt1.so:DEFAULT ]]
  59.  
  60.     The above runtime-linking method will give the full memory-corruption
  61.     detection power of libdmalloc, but the stack tracing routines
  62.     will not work (and may core dump).  So if you want to
  63.     use libdmalloc to detect leaks, or if you want libdmalloc
  64.     to give you a stack trace of the original call to malloc
  65.     when corruption is detected, you will have to link the program
  66.     with libdmalloc.a and its dependent libraries.
  67.     The arguments to give the linker are:
  68.          libdmalloc.a -lmld -lexc -lmpc -lmangle
  69.     Try to link with .a's rather than .so's for the rest
  70.     of the libraries wherever possible; the stack tracing routines
  71.     really are not robust inside DSOs.
  72.  
  73. ===============================================================================
  74.  
  75. MEMORY CORRUPTION DETECTION
  76.  
  77.     CORE DUMPS THAT DON'T OCCUR WITH THE REGULAR MALLOC
  78.     If this happens, it probably means the program is using uninitialized
  79.         or freed memory; libdmalloc intentionally fills such regions
  80.         with a fill pattern to break such programs.
  81.  
  82.         If you are running a debugger on a program linked with libdmalloc
  83.         and you see the value "^A^A^A^A^A..." or 0x1010101 or 16843009
  84.         it usually means you are looking at an uninitialized malloced area;
  85.         if you see "^B^B^B^B^B..." or 0x2020202 or 33686018,
  86.         it usually means you are looking at an area that has been
  87.         freed already.
  88.  
  89.     UNDERFLOWS AND OVERFLOWS
  90.         When libdmalloc reports "overflow" corruption at a malloced address,
  91.         it means data has been illegally written past the end of the array.
  92.         Likewise "underflow" corruption means data has been illegally written
  93.         in the region immediately preceding the array.
  94.     libdmalloc checks at least the 8 bytes immediately
  95.         preceding and following the malloced array for
  96.         underflow and overflow corruption when the array is
  97.         free()d or realloc()ed, and all malloced arrays are checked
  98.     during exit().  When corruption is detected, error messages get
  99.     sent to stderr.
  100.  
  101.         Error messages for overflows and underflows look something like this:
  102.                 % oawk /./ /dev/null
  103.                 oawk(24863): ERROR: underflow corruption detected during free
  104.                         at malloc block 0x100d8fb0
  105.  
  106.         If you have compiled the program with libdmalloc.a
  107.         and the offending mallocs and frees aren't called
  108.         from within a DSO, you may be able to get libdmalloc to give you
  109.         stack traces of the free() and the original malloc():
  110.                 % unsetenv _RLD_LIST
  111.                 % setenv MALLOC_STACKTRACE_GET_DEPTH 10
  112.                 % oawk /./ /dev/null
  113.                 oawk(24879): ERROR: underflow corruption detected during free
  114.                         at malloc block 0x100d8fb0
  115.                    0 free() [dmalloc.c:892, 0x418000]
  116.                    1 freetr() [b.c:99, 0x40ccd0]
  117.                    2 freetr() [b.c:103, 0x40cd20]
  118.                    3 freetr() [b.c:108, 0x40cd5c]
  119.                    4 freetr() [b.c:103, 0x40cd20]
  120.                    5 makedfa() [b.c:65, 0x40cae8]
  121.                    6 yyparse() [awk.g.y:181, 0x40ac6c]
  122.                    7 main() [main.c:132, 0x40e984]
  123.                    8 __start() [crt1text.s:133, 0x409bb0]
  124.                 This block may have been allocated here:
  125.                    0 add() [b.c:284, 0x40d598]
  126.                    1 cfoll() [b.c:167, 0x40d07c]
  127.                    2 cfoll() [b.c:173, 0x40d0d0]
  128.                    3 cfoll() [b.c:177, 0x40d0ec]
  129.                    4 cfoll() [b.c:173, 0x40d0d0]
  130.                    5 makedfa() [b.c:62, 0x40cab8]
  131.                    6 yyparse() [awk.g.y:181, 0x40ac6c]
  132.                    7 main() [main.c:132, 0x40e984]
  133.                    8 __start() [crt1text.s:133, 0x409bb0]
  134.  
  135.         If not (e.g. if unshared libraries are not available,
  136.         or you don't want to recompile) you can probably
  137.         still track down the original malloc in the debugger.
  138.  
  139.             -- To stop the program when corruption
  140.                is detected, set a breakpoint in malloc_bad().
  141.  
  142.             -- To stop the program when malloc is about to fail (return 0),
  143.                set a breakpoint in malloc_failed().
  144.  
  145.             -- To stop the program when malloc is about to return
  146.                a particular address (say 0x100d8fb0, as in the above example)
  147.                    setenv MALLOC_BLOCK_OF_INTEREST 0x100d8fb0
  148.                and set a breakpoint in malloc_of_interest().
  149.  
  150.             -- If while running a program in the debugger
  151.                you want to know whether a given malloced array has overflowed
  152.                or underflowed yet, call malloc_isgoodblock(addr).
  153.                (See the above hint about using crt1.so to enable dbx to make
  154.                interactive calls if you are debugging a stripped program).
  155.                To check all malloced blocks at once, call malloc_check();
  156.                the returned value will be 0 for success,
  157.                or -1 (with error messages to stderr) if corruption is detected.
  158.            malloc_check() is called automatically during exit().
  159.  
  160.             [[ Hint: if you are using the _RLD_LIST variable and
  161.             the main program is stripped, dbx probably won't be able to find
  162.             symbols in libdmalloc.so until the program is actually running.
  163.             One way to do this is to set a breakpoint in getenv, run
  164.             the program until it stops in getenv (dbx will seg fault, but
  165.             don't worry, it's okay :-)), and then delete the breakpoint;
  166.             then the desired symbols should be visible. ]]
  167.  
  168.     SUPPRESSING ERROR MESSAGES
  169.         Certain known malloc overflow bugs always appear at a constant
  170.         address in a program; the MALLOC_SUPPRESS environment variable
  171.         can be used to suppress error messages about such bugs.
  172.         For example, if you are tired of seeing the following messages:
  173.             strings(24675): ERROR: overflow corruption detected during exit
  174.                 at malloc block 0x100010d0 (4 bytes)
  175.             CC(24678): ERROR: overflow corruption detected during exit
  176.                 at malloc block 0x1001b9d8 (5 bytes)
  177.         you can do the following:
  178.             setenv MALLOC_SUPPRESS " \
  179.                     CC:0x1001b9d8 \
  180.                     /bin/CC:0x1001b9d8 \
  181.                     /usr/bin/CC:0x1001b9d8 \
  182.                     strings:0x100010d0 \
  183.                     /bin/strings:0x100010d0 \
  184.             "
  185.     Note that there is a separate entry for each likely value of argv[0].
  186.     Note also that libdmalloc may not be able to determine argv[0]
  187.     if main() has overwritten it, so suppression may not always work.
  188.  
  189. ===============================================================================
  190.  
  191. LEAK DETECTION
  192. [[ XXX This section is slightly out-of-date; I haven't tried
  193.     this stuff in a while, and there may be better ways to do things now.
  194.     In particular, the new MALLOC_CHECK_ATEXIT environment variable
  195.     is probably a good way to look for leaks during exit().
  196.     CaseVision probably does a better job of all this anyway.  ]]
  197.  
  198.     libdmalloc also contains the additional functions and variables,
  199.     defined in "dmalloc.h":
  200.         void malloc_reset();
  201.                 Sets all counts to zero.
  202.         void malloc_info(int nonleaks_too, int stacktrace_print_depth);
  203.                 Prints out stacktraces of all leaks that have occurred
  204.                 since the last call to malloc_reset() (actually
  205.                 prints a histogram indexed by stack trace).
  206.                 If nonleaks_too is nonzero, the stacktraces of all
  207.                 mallocs and frees (not just leaks) will be printed.
  208.                 The stacktrace_print_depth argument specifies how
  209.                 much of each stacktrace you want to see; -1 means
  210.                 the entire trace (which is limited by the
  211.                 malloc_stacktrace_get_depth variable, see below).
  212.                 If the environment variable MALLOC_INFO_ATEXIT
  213.                 is set, then malloc_info(0,-1) will be called during exit().
  214.         void malloc_info_cleanup();
  215.                 Frees all resources opened by malloc_info().
  216.                 malloc_info() reads the symbol table of the executable
  217.                 object file (and all shared objects on which the executable
  218.                 depends) the first time it needs to look up
  219.                 a function name, file name and line number from a pc address;
  220.                 this is very time-consuming, so it leaves these
  221.                 files and symbol tables open.
  222.                 malloc_info_cleanup() attempts to close them and free the space.
  223.                 NOTE: as of this writing, libmld leaks like a sieve
  224.                 (see incident #176726) so malloc_info_cleanup may not
  225.                 be very effective.
  226.         void malloc_failed();
  227.                 This no-op function gets called whenever malloc fails
  228.                 for any reason.  It exists solely for breakpoint debugging.
  229.         int malloc_stacktrace_get_depth;
  230.                 This integer controls how deep a stacktrace to get and store
  231.                 at each malloc and free.
  232.                 Its initial value is 0, or the
  233.                 value of the environment variable MALLOC_STACKTRACE_GET_DEPTH
  234.                 if set.  Applications may change this value
  235.                 at any time.  There is a hard-coded max depth of 10
  236.                 (to change this, recompile this library with
  237.                 -DMAX_STACKTRACE_DEPTH=20 or whatever).
  238.                 Values less than 0 or greater than the max depth
  239.                 are taken to mean the max depth.
  240.         int malloc_fillarea;
  241.                 If nonzero, then newly malloced memory will be
  242.                 initialized to 1's and newly freed memory will
  243.                 be filled with 2's.
  244.                 The initial value of this variable is nonzero.
  245.                 I recommend not changing it.
  246.         void malloc_init_function();
  247.                 This is a no-op function that gets called at the
  248.                 beginning of the very first call to malloc().
  249.                 It is designed to be overridden by applications
  250.                 if they wish to do things before the first malloc
  251.                 (putting code at the top of main() is not sufficient,
  252.                 since malloc can get called by pre-main initialization
  253.                 routines).
  254.                 For example, libmallocGadget's version of this function
  255.                 looks for the environment variables
  256.                 MALLOC_GADGET_STACKTRACE_GET_DEPTH and MALLOC_GADGET_M_KEEP
  257.                 and sets malloc_stacktrace_get_depth and mallopt()
  258.                 appropriately.  Note that this overrides env
  259.                 MALLOC_STACKTRACE_GET_DEPTH; (i.e. MALLOC_STACKTRACE_GET_DEPTH
  260.                 has no effect when using the malloc gadget).
  261.  
  262. ===============================================================================
  263.  
  264. EXAMPLE OF FINDING LEAKS USING LIBDMALLOC AND DBX:
  265.  
  266.         Compile the program using the libraries specified above.
  267.         % dbx leaky_program
  268.         (dbx) when in main { assign malloc_stacktrace_get_depth = -1 }
  269.                                         (make sure stacktraces are gathered
  270.                                          on each malloc and free)
  271.         (dbx) stop at 10                (break prior to suspected leak)
  272.         (dbx) stop at 20                (break after suspected leak)
  273.         (dbx) run
  274.         Process 2916 (leaky_program) stopped at leaky_program.c:10
  275.         (dbx) ccall malloc_info(0,0)    (make sure symbol table is loaded
  276.                                          before reset, so it doesn't interfere
  277.                                          with the statistics)
  278.         (dbx) ccall malloc_reset()      (reset all counts to 0)
  279.         (dbx) cont
  280.         Process 2916 (leaky_program) stopped at leaky_program.c:20
  281.         (dbx) ccall malloc_info(0,0)    (print leaks since last reset)
  282.         (dbx) ccall malloc_info(0,-1)   (print leaks since last reset,
  283.                                          with full stacktraces)
  284.         (dbx) ccall malloc_info(1,0)    (print all mallocs & frees since last
  285.                                          reset)
  286.         (dbx) ccall malloc_info(1,3)    (print all mallocs & frees since last
  287.                                          reset, with stacktraces shown to
  288.                                          depth of 3)
  289.  
  290. ===============================================================================
  291.  
  292. ENVIRONMENT VARIABLES LIBDMALLOC LOOKS AT
  293.  
  294.     MALLOC_BLOCK_OF_INTEREST (default=0)
  295.         If set to an address, libdmalloc will call the no-op
  296.         function malloc_of_interest() during all mallocs which
  297.         return the given address.
  298.         This may be useful for finding the original
  299.         malloc of a corrupt block in a deterministic program;
  300.         simply setenv MALLOC_BLOCK_OF_INTEREST to be the address
  301.         given in the corruption error message, and use the debugger
  302.         to stop in malloc_of_interest().
  303.     MALLOC_CALL_OF_INTEREST (default=-1)
  304.         If set to a non-negative integer n, the n'th call
  305.         to malloc will call the no-op function malloc_of_interest().
  306.         This can be used if you wish to stop in the n'th call to malloc()
  307.         in the debugger.
  308.     MALLOC_CHECK_ATEXIT (default=1)
  309.         If this variable is nonzero (as it is by default),
  310.         all malloced blocks will be checked for overflow and
  311.         underflow corruption during exit().
  312.         If set to a value >= 2, a message will be printed to stderr
  313.         during this check, something like:
  314.             ls(24659): Checking malloc chain at exit...done.
  315.         This will keep you informed of which programs you are running
  316.         are actually using libdmalloc.
  317.         Keep in mind, however, that some programs
  318.         (e.g. p_finalize and inst) will abort if they detect
  319.         any stderr output from a child process.
  320.     MALLOC_FILLAREA (default=1)
  321.         If nonzero (as it is by default), malloc() and realloc()
  322.         will fill all uninitialized
  323.         bytes with the value of this variable, and free() and realloc()
  324.         will fill all free'd bytes with 2's.
  325.     MALLOC_INFO_ATEXIT (default=0)
  326.     If this variable is set, malloc_info(0,-1) will
  327.     be called during exit().
  328.     MALLOC_PROMPT_ON_STARTUP
  329.         If set, during the first call to malloc(),
  330.         the following message will be sent to /dev/tty:
  331.             <commandname>(<process-id>): hit return to continue
  332.         and one character will be read from /dev/tty before continuing.
  333.         This may be useful for identifying "mystery programs" that
  334.         are being run from other programs.
  335.     MALLOC_STACKTRACE_GET_DEPTH (default=0)
  336.     Initializes the value of the malloc_stacktrace_get_depth
  337.     variable, which controls the depth of the stack trace
  338.     to store during each malloc.  See "malloc_stacktrace_get_depth"
  339.     above for more info.
  340.     MALLOC_SUPPRESS
  341.         Use this variable to suppress messages coming
  342.         from a particular program at a particular address.
  343.         See "SUPPRESSING ERROR MESSAGES" above for details.
  344.     _MALLOC_TRY_TO_PRINT_STACKTRACES
  345.         If set, an attempt will be made to print stacktraces on error,
  346.         even if _RLD_LIST is set.  (Usually stack traces are not
  347.         attempted if _RLD_LIST is set, since _RLD_LIST usually
  348.         means libdmalloc.so is being used, which means stack tracing
  349.         will probably core dump).
  350.     _MALLOC_DONT_TRY_TO_PRINT_STACKTRACES
  351.         If set, no attempt will be made to print stacktraces on error,
  352.         even if _RLD_LIST is not set. (see _MALLOC_TRY_TO_PRINT_STACKTRACES).
  353.     _STACKTRACE_ARGV0
  354.         If set, the function stacktrace_get_argv0() will
  355.         return the value of this variable, rather than trying
  356.         to get the value of argv[0] from the stack.
  357.         This may be useful for programs whose main() overwrites
  358.         argv.
  359.